//
//		Author: Alexandros Sigalas
//
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.

#ifndef POLYGON
#define POLYGON

#include "globals.h"
#include "material.h"
#include "mathutils.h"
#include "bounds.h"

enum PL_Order{CW=0, CCW};
enum PL_Attr{HIDDEN=1, SECTION=2, BACKF=4, CLIPPED=8, HOLE=16};

struct Polygon;

typedef struct PL_List{
	struct Polygon **polys;
	uint last, size;
}*polylist;

struct PL_Props{
	uint coplanar_id;
	uint crease_id;
	float shade_f;
};

struct PL_Vertex{
	struct Vec co;
	int flags;
};

typedef struct Polygon{
	struct PL_Vertex *points;
	uint size, last;
	int flag;
	int attr;
	struct Bounds bb;
	struct PL_List *holes;
	struct PL_Props props;
	struct VR_Material *mat;
}*polygon;

polygon pl_init(const uint count);

polygon pl_copy(const polygon pl, void (*copy_method)(vec *dest, const vec * const src), const int holes);

void pl_kill(polygon *pl);

struct PL_Vertex *pl_append(polygon *pl, const vec * const co, const int flag);
struct PL_Vertex *pl_append_point(polygon *pl, const vec * const co);
struct PL_Vertex *pl_append_vertex(polygon *pl, const struct PL_Vertex * const vx);

struct PL_Vertex *pl_insert(polygon pl, const uint pos, const vec * const co, const int flag);
struct PL_Vertex *pl_insert_point(polygon pl, const uint pos, const vec * const co);
struct PL_Vertex *pl_insert_vertex(polygon pl, const uint pos, const struct PL_Vertex * const vx);

struct PL_Vertex *pl_pop(polygon pl);
struct PL_Vertex *pl_remove(polygon pl, const uint idx);
struct PL_Vertex *pl_remove_vertex(polygon pl, const struct PL_Vertex * const vx);

void pl_extend_points(polygon pl, const vec * const points, const uint count);
void pl_extend_verts(polygon pl, const struct PL_Vertex * const verts, const uint count);

int pl_add_hole(polygon pl, const polygon hole);
int pl_self_intersects(const polygon pl, enum axis_pair ax);
void pl_reverse(polygon pl);

int pl_rel_point_2d(const polygon pl, const vec * const p, const enum axis_pair ax, const int holes);
int pl_rel_plane(const polygon pl, const vec * const pp, const vec * const pn, int *rmap);

double pl_area_2d( const polygon pl, const enum axis_pair ax, const int holes);
double pl_area_3d( const polygon pl, const int holes);

void pl_normal(const polygon pl, vec * normal);

uint pl_simplify_2d(polygon pl, enum axis_pair ax);
uint pl_simplify_3d(polygon pl);
uint pl_rm_doubles_2d(polygon pl, enum axis_pair ax);
uint pl_rm_doubles_3d(polygon pl);

enum PL_Order pl_order(const polygon pl);
enum PL_Order pl_order_2d(const polygon pl, const enum axis_pair ax);

void pl_prj_to_plane( polygon pl,
                      const vec * const pp, const vec * const pn,
                      const vec * const direction);

int pl_split_by_plane(const polygon pl,
					  const vec * const pp, const vec * const pn, 
					  polylist *fparts, polylist *bparts, int do_holes);

///// polylist

polylist pll_init(const uint count);

void pll_kill(polylist *pll);
void pll_killall(polylist * pll);

polylist pll_copy(const polylist pll, void (*copy_method)(vec *dest, const vec * const src));

void pll_append(polylist *pll, const polygon pl);
polygon pll_insert(polylist pll, const uint pos, const polygon pl);
polygon pll_pop(polylist pll);

polygon pll_remove(polylist pll, const uint idx);
int pll_remove_pl(polylist pll, const polygon pl);

polygon pll_replace(polylist pll, const uint idx, const polygon pl);
int pll_replace_pl(polylist pll, const polygon to_replace, const polygon pl);

void pll_extend(polylist *pll, const polygon * const polys, const uint count);

void pll_sort_by_area(polylist pll);
uint pll_count_points(polylist pll);

#endif
